using System;
using System.Collections.Generic;
using System.Diagnostics;
using Rhizome.Contract;
using Rhizome.Contract.Diag;
using Rhizome.Model.Validation;

namespace Rhizome.Model
{
	public sealed class IfMessage : RhizomeElement, ICriterion, IValidate
	{
		private bool _isMessageSet;
		private IMessage _message;
		internal IMessage CurrentMessage { private get; set; }

		/// <summary>
		/// Inner criterion. Message will replace Plant
		/// </summary>
		public ICriterion Criterion
		{
			[DebuggerStepThrough]
			get
			{
				ICriterion c;
				return TryGetInternalValue(CriterionProperty, out c) ? c : null;
			}
			[DebuggerStepThrough]
			set { SetValue(CriterionProperty, value); }
		}

		public IMessage Message
		{
			[DebuggerStepThrough]
			get { return _message; }
			[DebuggerStepThrough]
			set
			{
				_message = value;
				_isMessageSet = true;
			}
		}

		#region Overrides of RhizomeElement

		public override T GetValue<T>(RhizomeProperty<T> property)
		{
			if (ReferenceEquals(PlantProperty, property))
			{
				return 
					CurrentMessage == null
						? (T) Message // for validation
						: (T) CurrentMessage;
			}

			return base.GetValue(property);
		}

		#endregion

		#region Implementation of ICriterion

		bool ICriterion.Test()
		{
			if (Equals(Message, CurrentMessage) == false) 
				return false;

			var c = Criterion;
			return c == null || c.Test();
		}

		#endregion

		#region Implementation of IValidate

		public IEnumerable<IValidationResult> GetValidationResults()
		{
			if (_isMessageSet == false) yield return ValidationResult.MessageNotSet;
		}

		#endregion

		public override string ToString()
		{
			return string.Format("IfMessage {0}", Message);
		}
	}
}